home *** CD-ROM | disk | FTP | other *** search
- #
- # stochastic arp editor
- #
- # edit a stochastic arpeggiator matrix while playing it
- #
-
- @include c:\mbin\mh\wind.mh
- @include c:\mbin\mh\actions.mh
-
- #
- # stochastic array
- #
- # Probability 0..100
- # Last note means if the last note was X, then
- # choose this note. If last note column is the
- # new note column set back one. This increases
- # the odds of playing notes in the order given
- # (column-wise) of the next note array.
- #
- TRUE = 1
- FALSE = 0
-
- MAXARP = 100
-
- THISNOTE = 0
- THISTIME = 1
- NEXTNOTE = 2
- NEXTPROB = 3
-
- uchar arptable[MAXARP][4] = {
- LLA, e, LC, 70,
- LC, e, LB, 50,
- D#, e, LA, 70,
- LA, e, LB, 70,
- LB, e, C, 100,
- C, e, F#, 50,
- F#, e, G, 100,
- G, s, A, 50,
- G, s, D, 25,
- G, s, C, 25,
- G, s, E, 25,
- A, s, B, 0,
- B, t, HD, 100,
- HD, t, HE, 100,
- HE, t, HF#, 100,
- HF#, q, HE, 100
- }
-
- # how long in quarter notes to do stochArp call
- uchar howlong[1] = {
- 4
- }
-
- # enable/disable loop mode - continous loop play
- # of action
- #
- LOOPOFF = 0
- LOOP = 1
-
- # play action once, do nothing, print action in ascii file
- # should add binary save/load.
- BREAD = 0
- BWRITE = 1
- PLAY = 2
- PRINT = 3
- ZILCH = 4 # no command
-
- uchar loopOn[1]
- uchar editCom[1]
-
- NOCOLS = 4
- LSIZE = 5 # max label size
- FSIZE = 5 # field size
-
- riff printArp()
- int fd
- int i
- int rowcount
-
- fd = open("arp.ma",3)
-
- for ( i = 0; i < MAXARP; i++)
- if (arptable[i][0] == 0)
- break
- end
- end
- rowcount = i
-
- void fprintf(fd, "uchar arp[%d+1][4] = {\n",rowcount)
- for ( i = 0; i < MAXARP; i++)
- if (arptable[i][0] == 0)
- break
- end
- void fprintf(fd, "\t%n,\t%t,\t%n,\t%d,\n",arptable[i][0],arptable[i][1], arptable[i][2], arptable[i][3])
- end
- void fprintf(fd,"\t0\n")
- void fprintf(fd, "}\n")
- void close(fd)
- end
-
- # action window handle
- int arpwd
-
- riff openArpWindow()
- # put up action window first so that it gets
- # cursor
- arpwd = inputMWindow(WTABLE, 0, 0, 20, NOCOLS*FSIZE+2+LSIZE, "stocharp", 1, 5, 4, &arptable)
- void windowControl(arpwd, NOTETRANSLATION, 0, 0)
- void windowControl(arpwd, TIMETRANSLATION, 1, 0)
- void windowControl(arpwd, NOTETRANSLATION, 2, 0)
- end
-
-
- riff reopenActionWindow()
- void closeWindow(arpwd)
- void openArpWindow()
- end
-
- # default string name of action file
- uchar arpfile[20]={
- 'a','r','p','.','b',0
- }
-
-
- # write action array out as binary file
- riff writeBinary()
- int fd
-
- # open the file
- fd = open(&arpfile, 3)
- # write the acts array
- void printf("writing action file...")
- void write(fd, &arptable[0], MAXARP * 4)
- void close(fd)
- end
-
- # read action array back in as binary file and
- # update display
- riff readBinary()
- int fd
- int count
-
- fd = open(&arpfile, 0)
- void read(fd, &arptable[0], MAXARP * 4)
- void close(fd)
- void reopenActionWindow()
- end
-
-
- riff openWindows()
- int wd
-
- void openArpWindow()
- # define window for edit/play commands
- wd = inputWindow(WDEFINE, 9, 40, 12, 50, "loop", 2, 0, 0, &loopOn)
- void windowLabel(wd, "off", 0)
- void windowLabel(wd, "loop", 1)
- wd = inputWindow(WDEFINE, 13, 40, 18, 50, "command", 4, 0, 0, &editCom)
- void windowLabel(wd, "bread", 0)
- void windowLabel(wd, "bwrite", 1)
- void windowLabel(wd, "play", 2)
- void windowLabel(wd, "print", 3)
- wd = inputWindow(WNUMERIC, 19, 40, 21, 50, "arptime", 4, 5, 1, &howlong)
- void windowLabel(wd, "q's:", 0)
- # voicelist and rcc windows
- void mosWindow(WVCO,5,40)
- void mosWindow(WRCC,0,40)
- # debug window
- void outputWindow(WDEBUG,10,51,24,79,"printf") # halfway
- wd = inputWindow(WSTRING, 21, 0, 0, 0, "enter arpfile ", 1, 1, 19, &arpfile)
- end
-
- #
- # algorithm:
- #
- # play first
- # then make probability transition
- #
- int lastindex = 0
- riff stochArp(matrix m, col, maxtime, startover)
- # matrix m - pointer to 2d uchar array
- # col - size of column of array
- # maxtime - maximum time arp should run
- # startover - don't use lastindex, set index to 0
- int i # general loop index
- int curindex # array index for playing
- int nextindex # next array index after search
- int rval # rand no.
- int curtime # how much time taken so far
- int remtime # how much time before stocharp returns
- int nexttime # time request taken from stoch array
- int row # no of rows before 0 note in array
- int candidate # candidate note to search array for
- int foundit # flag indicating if candidate was found
-
- # find end of stoch arp, 1st 0 or out of rows
- # indicates end.
- for ( i = 0; i < MAXARP; i++)
- if (m[i][0] == 0)
- break
- end
- end
- # put index in row to set array size
- row = i
- curtime = 0
- if (startover == 1)
- lastindex = 0
- end
- curindex = lastindex
-
- # loop thru while there is time
- for (curtime = 0;;)
-
- # PLAY THE NOTE FIRST
- # play the note
- remtime = maxtime - curtime
- void printf("rem %d, max %d, cur %d",remtime,maxtime,curtime)
- nexttime = m[curindex][THISTIME]
- # if remaining event time is less than
- # requested time, trucate request so
- # that overall SPAN passed in is exact
- # this also means we are about to return.
- if (remtime < nexttime )
- nexttime = remtime
- rval = mrandrange(1,100)
- if (rval < 33)
- void printf("tie %t",nexttime)
- tie nexttime
- else if (rval < 66)
- rest nexttime
- void printf("rest %t",nexttime)
- else
- void printf("[%d]:%n %t",curindex, m[curindex][0], nexttime)
- m[curindex][0] nexttime mrandrange(70,125)
- end
- else
- void printf("[%d]:%n %t",curindex, m[curindex][0], nexttime)
- m[curindex][0] nexttime mrandrange(70,125)
- end
- # update elapsed time
- curtime = curtime + nexttime
- # if elapsed time exceeds or is the same than
- # maxtime, quit
- if (curtime >= maxtime)
- return(1)
- end
-
- # NOW CHOOSE WHERE TO GO TO
-
- # choose nextnote according to probability.
- # if probability match occurs we SEARCH thru
- # the array for the next note (we play it if we find it)
- # if we don't find it, we just take the next iterative
- # note in the array to play
- candidate = m[curindex][NEXTNOTE]
-
- foundit = FALSE
- rval = mrandrange(0,100)
-
- # set nextindex to next note which is where we go
- # if probability match fails
- nextindex = curindex + 1
- # logical wrap
- if ( nextindex >= row)
- nextindex = 0
- end
- # if prob match succeeds
- if ( rval < m[curindex][NEXTPROB] )
- # search through remaining array from
- # current position to end FIRST, this
- # helps us to advance down
- for ( i = curindex; i < row; i++)
- if (m[i][THISNOTE] == candidate)
- foundit = TRUE
- nextindex = i
- break
- end
- end
- # if search failed, search from beginning to current.
- if (foundit == FALSE)
- for ( i = 0; i < curindex; i++)
- if (m[i][THISNOTE] == candidate)
- foundit = TRUE
- nextindex = i
- break
- end
- end
- end
- end
- # nextindex indicates WHERE we want to advance to
- # lastindex is stored in case we are called again
- lastindex = nextindex
- # curindex is what we use for playing the note
- curindex = nextindex
- end
- return(1)
- end
-
- riff doStochArp()
- void stochArp(&arptable, 4, howlong[0] * q, 1)
- end
-
- # work from edit/play DEFINE carrying out commands.
- #
-
- vco actedit()
- void openWindows()
-
- # poll for command change
- editCom[0] = ZILCH
- for(;;)
- switch(editCom[0])
- case PLAY:
- void doStochArp()
- editCom[0] = ZILCH
- end
- case PRINT:
- void printArp()
- editCom[0] = ZILCH
- end
- case BREAD:
- void readBinary()
- editCom[0] = ZILCH
- end
- case BWRITE:
- void writeBinary()
- editCom[0] = ZILCH
- end
- end
- rest 1
- end
- end
-
- # play action in LOOP mode
- vco playit
- int lastCom
- int doit
- loopOn[0] = LOOPOFF
- lastCom = LOOPOFF
- doit = 0
- for(;;)
- if (loopOn[0] != lastCom)
- lastCom = loopOn[0]
- if (loopOn[0] == LOOPOFF)
- doit = 0
- else
- doit = 1
- end
- end
- if (doit)
- void doStochArp()
- end
- rest 1
- end
- end
-
-